/***************************************************************************************************
 *Copyright(C),2010-2016,Sumscope
 *FileName	:  string_aes.cpp
 *Author	:  scofined.qi
 *Version	:  1.0
 *Date		:  2017/04/19
 *Desc		:  //用于主要说明此程序文件完成的主要功能
 *Relation :
 *Others	:  //其他内容说明
 *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
 *History	:
 * //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
 ***************************************************************************************************/
#include "string_aes.h"
// #include "./minizip/mzaes.h"
#include <string.h>

#include <string>

// using namespace std;
#pragma warning(disable : 4996)
#define PARAM_ERROR -1

#define CHECK_LOG(format, ...)      \
  if (false) {                      \
    BLOGERR(format, ##__VA_ARGS__); \
  }

namespace qb {
namespace base {
namespace {

#define MOD8(a) (a - ((a >> 3) << 3))
#define SWAP4(a, b)                           \
  *(int*)(a) = (*(int*)(a)) ^ (*(int*)(b));   \
  *((int*)(b)) = (*(int*)(b)) ^ (*(int*)(a)); \
  *((int*)(a)) = (*(int*)(a)) ^ (*(int*)(b));
#define SWAP8(a, b) \
  SWAP4(a, b);      \
  SWAP4((char*)a + 4, (char*)b + 4);
#define SWAP16(a, b) \
  SWAP8(a, b);       \
  SWAP8((char*)a + 8, (char*)b + 8);
#define SWAP32(a, b) \
  SWAP16(a, b);      \
  SWAP16((char*)a + 16, (char*)b + 16);

#define COPY8(DEST, SOURCE) *((double*)(DEST)) = *((const double*)(SOURCE));

#define COPY16(DEST, SOURCE)                       \
  *((double*)(DEST)) = *((const double*)(SOURCE)); \
  *((double*)(DEST) + 1) = *((const double*)(SOURCE) + 1);

#define COPY32(DEST, SOURCE)                               \
  *((double*)(DEST)) = *((const double*)(SOURCE));         \
  *((double*)(DEST) + 1) = *((const double*)(SOURCE) + 1); \
  *((double*)(DEST) + 2) = *((const double*)(SOURCE) + 2); \
  *((double*)(DEST) + 3) = *((const double*)(SOURCE) + 3);

#define COPY48(DEST, SOURCE)                               \
  *((double*)(DEST)) = *((const double*)(SOURCE));         \
  *((double*)(DEST) + 1) = *((const double*)(SOURCE) + 1); \
  *((double*)(DEST) + 2) = *((const double*)(SOURCE) + 2); \
  *((double*)(DEST) + 3) = *((const double*)(SOURCE) + 3); \
  *((double*)(DEST) + 4) = *((const double*)(SOURCE) + 4); \
  *((double*)(DEST) + 5) = *((const double*)(SOURCE) + 5);

#define COPY64(DEST, SOURCE)                               \
  *((double*)(DEST)) = *((const double*)(SOURCE));         \
  *((double*)(DEST) + 1) = *((const double*)(SOURCE) + 1); \
  *((double*)(DEST) + 2) = *((const double*)(SOURCE) + 2); \
  *((double*)(DEST) + 3) = *((const double*)(SOURCE) + 3); \
  *((double*)(DEST) + 4) = *((const double*)(SOURCE) + 4); \
  *((double*)(DEST) + 5) = *((const double*)(SOURCE) + 5); \
  *((double*)(DEST) + 6) = *((const double*)(SOURCE) + 6); \
  *((double*)(DEST) + 7) = *((const double*)(SOURCE) + 7);

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
/*初始置换表IP*/
const int IP_Table[64] = {57, 49, 41, 33, 25, 17, 9,  1,  59, 51, 43, 35, 27,
                          19, 11, 3,  61, 53, 45, 37, 29, 21, 13, 5,  63, 55,
                          47, 39, 31, 23, 15, 7,  56, 48, 40, 32, 24, 16, 8,
                          0,  58, 50, 42, 34, 26, 18, 10, 2,  60, 52, 44, 36,
                          28, 20, 12, 4,  62, 54, 46, 38, 30, 22, 14, 6};
/*逆初始置换表IP^-1*/
const int IP_1_Table[64] = {39, 7,  47, 15, 55, 23, 63, 31, 38, 6,  46, 14, 54,
                            22, 62, 30, 37, 5,  45, 13, 53, 21, 61, 29, 36, 4,
                            44, 12, 52, 20, 60, 28, 35, 3,  43, 11, 51, 19, 59,
                            27, 34, 2,  42, 10, 50, 18, 58, 26, 33, 1,  41, 9,
                            49, 17, 57, 25, 32, 0,  40, 8,  48, 16, 56, 24};
/*扩充置换表E*/
const int E_Table[48] = {31, 0,  1,  2,  3,  4,  3,  4,  5,  6,  7,  8,
                         7,  8,  9,  10, 11, 12, 11, 12, 13, 14, 15, 16,
                         15, 16, 17, 18, 19, 20, 19, 20, 21, 22, 23, 24,
                         23, 24, 25, 26, 27, 28, 27, 28, 29, 30, 31, 0};
/*置换函数P*/
const int P_Table[32] = {15, 6, 19, 20, 28, 11, 27, 16, 0,  14, 22,
                         25, 4, 17, 30, 9,  1,  7,  23, 13, 31, 26,
                         2,  8, 18, 12, 29, 5,  21, 10, 3,  24};
/*S盒*/
const int S[8][4][16] =
    /*S1*/
    {{{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
      {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
      {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
      {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
     /*S2*/
     {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
      {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
      {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
      {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
     /*S3*/
     {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
      {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
      {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
      {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
     /*S4*/
     {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
      {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
      {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
      {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
     /*S5*/
     {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
      {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
      {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
      {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
     /*S6*/
     {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
      {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
      {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
      {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
     /*S7*/
     {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
      {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
      {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
      {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
     /*S8*/
     {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
      {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
      {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
      {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}};
/*置换选择1*/
const int PC_1[56] = {56, 48, 40, 32, 24, 16, 8,  0,  57, 49, 41, 33, 25, 17,
                      9,  1,  58, 50, 42, 34, 26, 18, 10, 2,  59, 51, 43, 35,
                      62, 54, 46, 38, 30, 22, 14, 6,  61, 53, 45, 37, 29, 21,
                      13, 5,  60, 52, 44, 36, 28, 20, 12, 4,  27, 19, 11, 3};
/*置换选择2*/
const int PC_2[48] = {13, 16, 10, 23, 0,  4,  2,  27, 14, 5,  20, 9,
                      22, 18, 11, 3,  25, 7,  15, 6,  26, 19, 12, 1,
                      40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 46,
                      43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31};
/*对左移次数的规定*/
const int MOVE_TIMES[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};

//////////////////////////////////////////////////////////////////////////

/*字节转换成二进制*/
void ByteToBit(char ch, char bit[8]) {
  for (int cnt = 0; cnt < 8; cnt++) {
    *(bit + cnt) = (ch >> cnt) & 1;
  }
}
/*二进制转换成字节*/
void BitToByte(char bit[8], char* ch) {
  for (int cnt = 0; cnt < 8; cnt++) {
    *ch |= *(bit + cnt) << cnt;
  }
}
/*将长度为8的字符串转为二进制位串*/
int Char8ToBit64(char ch[8], char bit[64]) {
  for (int cnt = 0; cnt < 8; cnt++) {
    ByteToBit(*(ch + cnt), bit + (cnt << 3));
  }
  return 0;
}
/*将二进制位串转为长度为8的字符串*/
int Bit64ToChar8(char bit[64], char ch[8]) {
  int cnt = 0;
  memset(ch, 0, 8);
  for (cnt = 0; cnt < 8; cnt++) {
    BitToByte(bit + (cnt << 3), ch + cnt);
  }
  return 0;
}

/*密钥置换1*/
void DES_PC1_Transform(char key[64], char tempbts[56]) {
  for (int cnt = 0; cnt < 56; cnt++) tempbts[cnt] = key[PC_1[cnt]];
}
/*密钥置换2*/
void DES_PC2_Transform(char* key /*[56]*/, char* tempbts /*[48]*/) {
  for (int cnt = 0; cnt < 48; cnt++) tempbts[cnt] = key[PC_2[cnt]];
}
/*循环左移
  原始的代码存在bug:time只能为1或者2,
        memcpy(data, data + time, 28 - time);
        此时两个参数内存重叠

*/
int DES_ROL(char data[56], int time) {
  if ((data == NULL) || (time < 0)) {
    return PARAM_ERROR;
  }
  char temp[56] = {0};
  /*保存将要循环移动到右边的位*/
  memcpy(temp, data, time);
  memcpy(temp + time, data + 28, time);
  /*前28位移动*/
  memcpy(data, data + time, 28 - time);
  memcpy(data + 28 - time, temp, time);
  /*后28位移动*/
  memcpy(data + 28, data + 28 + time, 28 - time);
  memcpy(data + 56 - time, temp + time, time);
  return 0;
}
void ROL28_1(char data[28]) {
  char c = data[0];
  for (int i = 0; i < 27; i++) data[i] = data[i + 1];
  data[27] = c;
}
void ROL28_2(char data[28]) {
  char c = data[0], c2 = data[1];
  for (int i = 2; i < 28; i++) data[i - 2] = data[i];
  data[26] = c;
  data[27] = c2;
}

/*生成子密钥*/
void DES_MakeSubKeys(char* key /*[64]*/, char subKeys[16][48]) {
  char stemp56[56] = {0};
  memset(stemp56, 0, 56);
  DES_PC1_Transform(key, stemp56); /*PC1置换*/
  for (int cnt = 0; cnt < 16; cnt++) {
    /*16轮跌代，产生16个子密钥*/
    // DES_ROL(stemp56, MOVE_TIMES[cnt]);
    if (1 == MOVE_TIMES[cnt]) {
      ROL28_1(stemp56);
      ROL28_1(stemp56 + 28);
    } else {
      ROL28_2(stemp56);
      ROL28_2(stemp56 + 28);
    }
    /*循环左移*/
    DES_PC2_Transform(stemp56, subKeys[cnt]); /*PC2置换，产生子密钥*/
  }
}
/*IP置换*/
void DES_IP_Transform(char* data) {
  char stemp64[64] = {0};
  for (int cnt = 0; cnt < 64; cnt++) stemp64[cnt] = data[IP_Table[cnt]];
  COPY64(data, stemp64);
}
/*IP逆置换*/
void DES_IP_1_Transform(char data[64]) {
  char stemp64[64] = {0};
  for (int cnt = 0; cnt < 64; cnt++) stemp64[cnt] = data[IP_1_Table[cnt]];
  COPY64(data, stemp64);
}
/*扩展置换*/
void DES_E_Transform(char data[48]) {
  char stemp48[48] = {0};
  for (int cnt = 0; cnt < 48; cnt++) stemp48[cnt] = data[E_Table[cnt]];
  COPY48(data, stemp48);
}
/*P置换*/
void DES_P_Transform(char data[32]) {
  char temp[32] = {0};
  for (int cnt = 0; cnt < 32; cnt++) temp[cnt] = data[P_Table[cnt]];
  COPY32(data, temp);
}
/*异或*/
void DES_XOR(char* R /*[48]*/, char* L /*[48]*/, int count) {
  for (int cnt = 0; cnt < count; cnt++, R++, L++) *R ^= *L;
}
/*S盒置换*/
void DES_SBOX(char data[48]) {
  int cnt = 0;
  int line = 0;
  int row = 0;
  int output = 0;
  int cur1 = 0, cur2 = 0;
  for (cnt = 0; cnt < 8; cnt++) {
    cur1 = cnt * 6;
    cur2 = cnt << 2;
    /*计算在S盒中的行与列*/
    line = (data[cur1] << 1) + data[cur1 + 5];
    row = (data[cur1 + 1] << 3) + (data[cur1 + 2] << 2) +
          (data[cur1 + 3] << 1) + data[cur1 + 4];
    output = S[cnt][line][row];
    /*化为2进制*/
    data[cur2] = (output & 0X08) >> 3;
    data[cur2 + 1] = (output & 0X04) >> 2;
    data[cur2 + 2] = (output & 0X02) >> 1;
    data[cur2 + 3] = output & 0x01;
  }
}
/*交换*/
void DES_Swap(char left[32], char right[32]) {
  SWAP32(left, right);
  // char temp[32] = { 0 };
  // COPY32(temp, left);
  // COPY32(left, right);
  // COPY32(right, temp);
}

/*加密单个分组*/
int DES_EncryptBlock(char* plainBlock /*[8]*/, char subKeys[16][48],
                     char* cipherBlock /*[8]*/) {
  char plainBits[64] = {0};
  char copyRight[48] = {0};
  if ((plainBlock == NULL) || (subKeys == NULL) || (cipherBlock == NULL)) {
    return PARAM_ERROR;
  }
  memset(plainBits, 0, 64);
  memset(copyRight, 0, 48);
  int cnt = 0;
  Char8ToBit64(plainBlock, plainBits);
  /*初始置换（IP置换）*/
  DES_IP_Transform(plainBits);
  /*16轮迭代*/
  for (cnt = 0; cnt < 16; cnt++) {
    COPY32(copyRight, plainBits + 32);
    /*将右半部分进行扩展置换，从32位扩展到48位*/
    DES_E_Transform(copyRight);
    /*将右半部分与子密钥进行异或操作*/
    DES_XOR(copyRight, subKeys[cnt], 48);
    /*异或结果进入S盒，输出32位结果*/
    DES_SBOX(copyRight);
    /*P置换*/
    DES_P_Transform(copyRight);
    /*将明文左半部分与右半部分进行异或*/
    DES_XOR(plainBits, copyRight, 32);
    if (cnt != 15) {
      /*最终完成左右部的交换*/
      DES_Swap(plainBits, plainBits + 32);
    }
  }
  /*逆初始置换（IP^1置换）*/
  DES_IP_1_Transform(plainBits);
  Bit64ToChar8(plainBits, cipherBlock);
  return 0;
}
/*解密单个分组*/
int DES_DecryptBlock(char* cipherBlock /*[8]*/, char subKeys[16][48],
                     char* plainBlock /*[8]*/) {
  char plainBits[64] = {0};
  char copyRight[48] = {0};
  if ((plainBlock == NULL) || (subKeys == NULL) || (cipherBlock == NULL)) {
    return PARAM_ERROR;
  }
  memset(plainBits, 0, 64);
  memset(copyRight, 0, 48);
  int cnt = 0;

  Char8ToBit64(cipherBlock, plainBits);
  /*初始置换（IP置换）*/
  DES_IP_Transform(plainBits);

  /*16轮迭代*/
  for (cnt = 15; cnt >= 0; cnt--) {
    COPY32(copyRight, plainBits + 32);
    /*将右半部分进行扩展置换，从32位扩展到48位*/
    DES_E_Transform(copyRight);
    /*将右半部分与子密钥进行异或操作*/
    DES_XOR(copyRight, subKeys[cnt], 48);
    /*异或结果进入S盒，输出32位结果*/
    DES_SBOX(copyRight);
    /*P置换*/
    DES_P_Transform(copyRight);
    /*将明文左半部分与右半部分进行异或*/
    DES_XOR(plainBits, copyRight, 32);
    if (cnt != 0) {
      /*最终完成左右部的交换*/
      DES_Swap(plainBits, plainBits + 32);
    }
  }

  /*逆初始置换（IP^1置换）*/
  DES_IP_1_Transform(plainBits);
  Bit64ToChar8(plainBits, plainBlock);
  return 0;
}

}  // namespace
StringAes::StringAes(const char* tag) {
  memset(bKey, 0, 64);
  for (int i = 0; i < 16; i++) memset(subKeys[i], 0, 48);

  SetTag(tag);
}
void StringAes::SetTag(const char* tag) {
  memset(keyBlock, 0, 16);
  COPY8(keyBlock, tag);           /*设置密钥*/
  Char8ToBit64(keyBlock, bKey);   /*将密钥转换为二进制流*/
  DES_MakeSubKeys(bKey, subKeys); /*生成子密钥*/
}
int StringAes::Encrypt(const char* pszInText, int insize, char* dataencrypted,
                       int outsize) {
  if (pszInText == NULL || insize <= 0 || dataencrypted == NULL) return false;
  if (insize > outsize || MOD8(outsize) != 0) return 0;

  memcpy(dataencrypted, pszInText, insize);
  if (outsize > insize) memset(dataencrypted + insize, 0, outsize - insize);
  return EncryptInPlace(dataencrypted, insize, outsize);
}
int StringAes::Decrypt(const char* pszInText, int insize, char* datadecrypted,
                       int outsize) {
  /*
  将长度为insize的数据pszInText进行解码
  条件:insize必须是8的整数倍,outsize必须>insize
  返回:<=insize
  */
  if (pszInText == NULL || insize <= 0 || datadecrypted == NULL || outsize <= 0)
    return false;

  if (MOD8(insize) != 0 || outsize < insize) return 0;
  memcpy(datadecrypted, pszInText, insize);
  if (outsize > insize) memset(datadecrypted + insize, 0, outsize - insize);
  return DecryptInPlace(datadecrypted, insize, outsize);
}
int StringAes::EncryptInPlace(char* buf, int size, int capcity) {
  if (buf == 0 || size <= 0 || size > capcity || MOD8(capcity) != 0) {
    return 0;
  }
  int nloop = size >> 3;
  int ntail = size - (nloop << 3);
  char plainBlock[9] = {0};
  char cipherBlock[9] = {0};

  char* pch = buf;
  const char* pchEnd = buf + (nloop << 3);
  for (; pch < pchEnd; pch += 8) {
    COPY8(plainBlock, pch);
    DES_EncryptBlock(plainBlock, subKeys, cipherBlock);
    COPY8(pch, cipherBlock);
  }

  // 最后不足8个字节,以0填充,最后一个以实际长度填充,加密后的长度永远都是8的整数倍
  if (ntail > 0) memcpy(plainBlock, pch, ntail);
  memset(plainBlock + ntail, '\0', 7 - ntail);
  plainBlock[7] = ntail;
  DES_EncryptBlock(plainBlock, subKeys, cipherBlock);
  COPY8(pch, cipherBlock);
  nloop++;
  return nloop << 3;
}
int StringAes::DecryptInPlace(char* buf, int size, int capcity) {
  /*
  将长度为insize的数据pszInText进行解码
  条件:insize必须是8的整数倍,outsize必须>insize
  返回:<=insize
  */
  if (buf == 0 || size <= 0 || size > capcity || MOD8(size) != 0) {
    return 0;
  }

  int nloop = size >> 3;
  int ntail = size - (nloop << 3);
  if (ntail != 0) {
    return 0;
  }

  char plainBlock[9] = {0};
  char cipherBlock[9] = {0};
  char* pch = buf;
  const char* pchEnd = buf + (nloop << 3);
  for (; pch < pchEnd; pch += 8) {
    COPY8(cipherBlock, pch);
    DES_DecryptBlock(cipherBlock, subKeys, plainBlock);
    COPY8(pch, plainBlock);
  }
  ntail = plainBlock[7];  // 原始最末位8个字节的实际数据长度
  if (ntail >= 8 || ntail < 0) {
    return 0;
  }
  pch -= 8;
  memset(pch + ntail, 0, 8 - ntail);
  return size - 8 + ntail;
}

int Encrypt(const char* pszInText, int insize, char* dataencrypted, int outsize,
            const char* key) {
  StringAes ae(key);
  return ae.Encrypt(pszInText, insize, dataencrypted, outsize);
}
int Decrypt(const char* pszInText, int insize, char* datadecrypted, int outsize,
            const char* key) {
  StringAes ae(key);
  return ae.Decrypt(pszInText, insize, datadecrypted, outsize);
}
//////////////////////////////////////////////////////////////////////////
typedef const unsigned char* lpcustr;
typedef unsigned char* lpustr;
class AesCoderImpl {
  //	aes_encrypt_ctx	m_encrypt[1];
  //	aes_decrypt_ctx	m_decrypt[1];
 public:
  AesCoderImpl(lpcustr key) { SetKey(key); }
  void SetKey(const unsigned char* key) {
    unsigned char keyblock[130] = {0};
    memset(keyblock, 0, 130);
#if WIN32
    strncpy_s((char*)keyblock, 130, (const char*)key, -1);
#else
    strncpy((char*)keyblock, (const char*)key, 130);
    if (keyblock[129] != '\0') keyblock[129] = '\0';
#endif
    //				aes_encrypt_key128(keyblock, m_encrypt);
    //				aes_decrypt_key128(keyblock, m_decrypt);
  }
  int Encrypt(const char* pszInText, int insize, char* dataencrypted,
              int outsize) {
    int nloop = insize >> 4;
    int ntail = insize - (nloop << 4);
    const unsigned char* source = (const unsigned char*)pszInText;
    unsigned char* dest = (unsigned char*)dataencrypted;
    const unsigned char* send = source + (insize - ntail);
    unsigned char padding[16] = {0};
    bool equal = false;
    for (; source < send; source += 16, dest += 16) {
      //					aes_encrypt(source, dest,
      //m_encrypt);
    }
    if (ntail > 0) memcpy(padding, source, ntail);
    memset(padding + ntail, 0, 16 - ntail);
    padding[15] = ntail;
    //				aes_encrypt(padding, dest, m_encrypt);
    return (nloop << 4) + 16;
  }
  int Decrypt(const char* pszInText, int insize, char* datadecrypted,
              int outsize) {
    int nloop = insize >> 4;
    int ntail = insize - (nloop << 4);
    const unsigned char* source = (const unsigned char*)pszInText;
    unsigned char* dest = (unsigned char*)datadecrypted;
    const unsigned char* send = source + (insize - ntail);
    for (; source < send; source += 16, dest += 16) {
      //					aes_decrypt(source, dest,
      //m_decrypt);
    }
    dest -= 16;
    ntail = dest[15];
    if (ntail >= 16 || ntail < 0) return 0;
    memset(dest + ntail, 0, 16 - ntail);
    return insize - 16 + ntail;
  }
};
BlockAes::BlockAes(const char* tag) { m_impl = new AesCoderImpl((lpcustr)tag); }
BlockAes::~BlockAes() {
  if (m_impl) delete m_impl;
}
void BlockAes::SetTag(const char* tag) {
  m_impl->SetKey((const unsigned char*)tag);
}
int BlockAes::Encrypt(const char* pszInText, int insize, char* dataencrypted,
                      int outsize) {
  return m_impl->Encrypt(pszInText, insize, dataencrypted, outsize);
}
int BlockAes::Decrypt(const char* pszInText, int insize, char* datadecrypted,
                      int outsize) {
  return m_impl->Decrypt(pszInText, insize, datadecrypted, outsize);
}
}  // namespace base
}  // namespace qb
